package edu.tamu.cse.teamproject1.Database;

import java.util.Date;

import edu.tamu.cse.teamproject1.Database.Interfaces.IColumnDefinition;
import edu.tamu.cse.teamproject1.Database.Interfaces.ITupleElement;

/**
 * 
 * @author Ben Unsworth
 * This defines the Columns, there type, 
 * and whether they are a key or not
 *
 */

public class ColumnDefinition implements IColumnDefinition {

	EnumColumnType type;
	String name;
	boolean key;
	int size;
	boolean nullable;
	
	/**
	 * constructor, creates a new column in a table
	 * the columns name is defined and its type
	 * the key is set as false because it was not defined
	 * @param newType, columnName
	 */
	public ColumnDefinition(EnumColumnType newType, String columnName){
		type = newType;
		name = columnName;
		key = false;
	}
	
	/**
	 * constructor, creates a new column in a table
	 * key is defined and its name and type
	 * @param newType, columnName, keyIs
	 */
	public ColumnDefinition(EnumColumnType newType, String columnName, boolean keyIs){
		type = newType;
		name = columnName;
		key = keyIs;		
	}	
	
	/**
	 * redefines the columns type
	 * @param newType
	 */
	public void setColumnType(EnumColumnType newType){
		type = newType;
	}
	
	/**
	 * redefines the columns type and whether it is a key or not
	 * @param newType, keyIs
	 */
	void setColumnType(EnumColumnType newType, boolean keyIs){
		type = newType;
		key = keyIs;
	}
	
	/**
	 * 
	 * @return the Column's Type
	 */
	public EnumColumnType getColumnType(){
		return type;
	}
	
	/**
	 * renames the column
	 * @param columnName
	 */
	public void setColumnName(String columnName){
		name = columnName;
	}
	
	/**
	 * 
	 * @return the column name
	 */
	public String getColumnName(){
		return name;
	}
	
	/**
	 * returns the key's status
	 * @return
	 */
	public boolean isKey(){
		return key;
	}

	/**
	 * sets whether the column is a key or not
	 * @param keyIs
	 */
	@Override
	public void setAsKey(boolean keyIs) {
		key = keyIs;
	}

	/**
	 * Takes a value, determines its type, and then generates
	 * a proper TupleElement based on that value
	 * @param value
	 * @return generatedTuple
	 */
	@Override
	public ITupleElement createTupleElement(Object value, String columnName) {
		// size, nullable, and type should already be set when using the constructor
		ITupleElement newElem = null;
		
		/*determines what the value's type should be and cast's it to that type*/ 
		if (value instanceof Integer) {
			newElem = new TupleIntegerElement((Integer) value);
		} else if (value instanceof String) {
			newElem = new TupleVarCharElement((String) value);
		} else if (value instanceof varchar){
			newElem = new TupleVarCharElement((varchar) value);
		} else if (value instanceof Float){
			newElem = new TupleFloatElement((Float) value);
		} else if (value instanceof Date){
			newElem = new TupleDateElement((Date) value);
		} else {
			throw new IllegalArgumentException("Invalid Object");
		}
		/*sets the columnName that the Tuple Element is associated with*/
		newElem.setColumnName(columnName);
		// Sets other attributes for the tuple
		newElem.setNullable(this.nullable);
		newElem.setAsKey(this.key);
		return newElem;
	}
	
	/**
	 * Creates an empty tuple element
	 * 
	 * @return An empty value tuple element
	 */
	@Override
	public ITupleElement createEmptyTupleElement() {
		ITupleElement newElem = null;
		
		/*determines the type of the empty tupleElement based upon the column created*/
		if (this.getColumnType() == EnumColumnType.integer) {
			newElem = new TupleIntegerElement(0);
		} else if (this.getColumnType() == EnumColumnType.character) {
			newElem = new TupleVarCharElement(new varchar(""));
		} else if (this.getColumnType() == EnumColumnType.varchar) {
			newElem = new TupleVarCharElement(new varchar(""));
		} else if (this.getColumnType() == EnumColumnType.floating) {
			newElem = new TupleFloatElement(0.0F);
		} else if (this.getColumnType() == EnumColumnType.date) {
			newElem = new TupleDateElement((Date) null);
		} else {
			throw new IllegalArgumentException("Invalid Object");
		}
		// Set the column name for this tuple.
		newElem.setColumnName(this.getColumnName());
		// Sets other attributes for the tuple
		newElem.setNullable(this.nullable);
		newElem.setAsKey(this.key);
		return newElem;
	}

	/**
	 * Returns the size of the column
	 * @return size
	 */
	@Override
	public int getColumnSize() {
		return size;
	}

	/**
	 * Determines is capable of being null
	 * @return columnNullableStatus
	 */
	@Override
	public boolean isNullable() {
		boolean columnNullableStatus;
		if(nullable == true){
			columnNullableStatus = true;
			return columnNullableStatus;
		}
		else{
			columnNullableStatus = true;
			return columnNullableStatus;
		}
	}

	/**
	 * Sets the columns size
	 * @param colmunSize
	 */
	@Override
	public void setColumnSize(int columnSize) {
		size = columnSize;
		
	}

	/**
	 * Sets whether the column is capable of being null
	 * @param colmunNullable
	 */
	@Override
	public void setNullable(boolean columnNullable) {
		nullable = columnNullable;
	}

	/**
	 * Implements deep copying for the object
	 * 
	 * @return Copy of this Column Definition
	 */
	@Override
	public Object clone() {
		try {
			return super.clone();
		} catch (CloneNotSupportedException e) {
			return null;
		}
	}
}
